package net.wangds.utils;

import net.wangds.common.base.module.Pair;
import net.wangds.log.helper.LogHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtils {

    @FunctionalInterface
    public interface UpdateTimeProc {
        void proc(Date dt, long tm, String txtDate, String txtTime);
    }

    @SuppressWarnings({"WeakerAccess"})
    public static final String DEFAULT_FORMATE = "yyyy-MM-dd HH:mm:ss";
    @SuppressWarnings({"WeakerAccess"})
    public static final String FULL_DATE_FORMATE = "yyyy-MM-dd HH:mm:ss.SSS";

    @SuppressWarnings({"WeakerAccess"})
    public static Date from(String text, String format){
        if(StringUtils.isBlank(text)){
            return new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(text);
        } catch (ParseException e) {
            LogHelper.warn(()->"字符串\""+text+"\"格式('"+format+"')不正确，无法解析为时间."+e.getLocalizedMessage(),e);
            return new Date();
        }
    }

    @SuppressWarnings("unused")
    public static Date ofTm(long tm){
        return new Date(tm);
    }

    @SuppressWarnings("unused")
    public static void updateTimeProc(long tm, UpdateTimeProc proc){
        if(proc==null){
            return;
        }
        Date dt = new Date(tm);
        String date = toYYYY_MM_DD(dt);
        String time = toHH_MM_SS(dt);
        proc.proc(dt, tm, date, time);
    }

    @SuppressWarnings("unused")
    public static void updateTimeProc(UpdateTimeProc proc){
        if(proc==null){
            return;
        }
        Date dt = new Date();
        long tm = dt.getTime();
        String date = toYYYY_MM_DD(dt);
        String time = toHH_MM_SS(dt);
        proc.proc(dt, tm, date, time);
    }


    @SuppressWarnings("unused")
    public static Date fromYYYY_MM_DD_HH_MM_SS(String text){
        return from(text, DEFAULT_FORMATE);
    }

    @SuppressWarnings({"unused","WeakerAccess"})
    public static String toYYYY_MM_DD_HH_MM_SS(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_FORMATE);
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static String toYYYY_MM_DD_HH_MM_SS(long tm) {
        return toYYYY_MM_DD_HH_MM_SS(new Date(tm));
    }

    @SuppressWarnings("unused")
    public static Date fromYYYY_MM_DD_HH_MM_SS_SSS(String text){
        return from(text, FULL_DATE_FORMATE);
    }

    @SuppressWarnings("unused")
    public static String toYYYY_MM_DD_HH_MM_SS_SSS(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat(FULL_DATE_FORMATE);
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromYYYYMMDDHHMMSSSSS(String text){
        return from(text, "yyyyMMddHHmmssSSS");
    }

    @SuppressWarnings("unused")
    public static String toYYYYMMDDHHMMSSSSS(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromYYYY_MM_DD_HH_MM(String text){
        return from(text, "yyyy-MM-dd HH:mm");
    }

    @SuppressWarnings("unused")
    public static String toYYYY_MM_DD_HH_MM(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromMM_DD_HH_MM(String text){
        return from(text, "MM-dd HH:mm");
    }

    @SuppressWarnings("unused")
    public static String toMM_DD_HH_MM(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "MM-dd HH:mm");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromYYYY_MM_DD(String text){
        return from(text, "yyyy-MM-dd");
    }

    @SuppressWarnings({"unused","WeakerAccess"})
    public static String toYYYY_MM_DD(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromYYYYMMDD(String text){
        return from(text, "yyyyMMdd");
    }

    @SuppressWarnings("unused")
    public static String toYYYYMMDD(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static int toYYYYMMDD_AsInt(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd");
        return Integer.parseInt(sdf.format(date==null?new Date():date));
    }

    @SuppressWarnings("unused")
    public static Date fromHH_MM(String text){
        return from(text, "HH:mm");
    }

    @SuppressWarnings("unused")
    public static String toHH_MM(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromHH_MM_SS(String text){
        return from(text, "HH:mm:ss");
    }

    @SuppressWarnings({"unused","WeakerAccess"})
    public static String toHH_MM_SS(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss");
        return sdf.format(date==null?new Date():date);
    }

    @SuppressWarnings("unused")
    public static Date fromYYYY_MM(String text){
        return from(text, "yyyy-MM");
    }

    @SuppressWarnings("unused")
    public static String toYYYY_MM(Date date){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM");
        return sdf.format(date==null?new Date():date);
    }


    /**
     * 当天零点.
     * @param dt 日期.
     * @return 零点.
     */
    public static Date getZeroTime(Date dt){
        Date res;

        if(dt==null){
            dt = new Date();
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String day = sdf.format(dt);
        String zero = day+"000000000";
        SimpleDateFormat sdfZero = new SimpleDateFormat("yyyyMMddHHmmsssSSS");
        try {
            res = sdfZero.parse(zero);
        } catch (ParseException e) {
            res = dt;
        }
        return res;
    }

    /**
     * 下一天零点.
     * @param dt 日期.
     * @return 下一天零点.
     */
    @SuppressWarnings("unused")
    public static Date getNextZeroTime(Date dt){
        Date res = getZeroTime(dt);
        Calendar cale = Calendar.getInstance();
        cale.setTime(res);
        cale.add(Calendar.DATE, 1);
        return cale.getTime();
    }

    /**
     *  格式:"yyyy-MM-dd HH:mm:ss".
     * @param date 时间.
     * @return 字符串.
     */
    public static String toDefaultString(Date date){
        return toString(date, DEFAULT_FORMATE, true, true);
    }

    public static Date parse(String date, String format, boolean defaultIsTodayOrNull){
        Date res = null;

        if(StringUtils.isNotBlank(date)&&StringUtils.isNotBlank(format)){
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try {
                res = sdf.parse(date);
            } catch (ParseException e) {
                LoggerFactory.getLogger(DateUtils.class).warn(e.getLocalizedMessage(), e);
            }
        }

        if(res==null&&defaultIsTodayOrNull){
            res = new Date();
        }
        return res;
    }

    public static String toString(Date date, String format, boolean nullIsToday, boolean defaultEmptyOrNull){
        String res = defaultEmptyOrNull?"":null;
        if(date==null){
            if(nullIsToday) {
                date = new Date();
            }else{
                return res;
            }
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     *  格式:"yyyy-MM-dd".
     * @param date 时间.
     * @return 字符串.
     */
    public static String toDefaultDateStr(Date date){
        if(date==null){
            date = new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }

    /**
     *  格式:"HH:mm:ss".
     * @param date 时间.
     * @return 字符串.
     */
    @SuppressWarnings("unused")
    public static String toDefaultTimeStr(Date date){
        if(date==null){
            date = new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(date);
    }

    /**
     *  格式:"yyyy-MM-dd HH:mm:ss.SSS".
     * @param date 时间.
     * @return 字符串.
     */
    public static String toFullTimeStr(Date date){
        if(date==null){
            date = new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return sdf.format(date);
    }

    @SuppressWarnings("unused")
    public static Pair<Date, Date> calcMonthBoundary(Date date){

        if(date==null){
            date = new Date();
        }

        Calendar calc = Calendar.getInstance();
        calc.setTime(date);
        calc.set(Calendar.DAY_OF_MONTH, calc.getActualMinimum(Calendar.DAY_OF_MONTH));
        calc.set(Calendar.HOUR, 0);
        calc.set(Calendar.MINUTE, 0);
        calc.set(Calendar.SECOND, 0);
        calc.set(Calendar.MILLISECOND, 0);
        Date start = calc.getTime();

        calc.set(Calendar.DAY_OF_MONTH, calc.getActualMaximum(Calendar.DAY_OF_MONTH));
        calc.set(Calendar.HOUR, 23);
        calc.set(Calendar.MINUTE, 59);
        calc.set(Calendar.SECOND, 59);
        calc.set(Calendar.MILLISECOND, 999);
        Date end = calc.getTime();

        return Pair.of(start, end);
    }




}
